#include <Arduino.h>
#include "u8g2_graph.h"
#include "config.h"

U8G2_Graph::U8G2_Graph(GraphType t, uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint16_t min_val, uint16_t max_val)
{
  this->init(t, x, y, width, height);
  this->min_val_i = min_val;
  this->max_val_i = max_val;
}

U8G2_Graph::U8G2_Graph(GraphType t, uint8_t x, uint8_t y, uint8_t width, uint8_t height, float min_val, float max_val)
{
  this->init(t, x, y, width, height);
  this->min_val_f = min_val;
  this->max_val_f = max_val;
}

U8G2_Graph::~U8G2_Graph()
{
  delete[] this->item_buffer;
}

void U8G2_Graph::init(GraphType t, uint8_t x, uint8_t y, uint8_t w, uint8_t h)
{
  this->type = t;
  this->x = x;
  this->y = y;
  this->width = w;
  this->height = h;
  this->min_height = 1;
  this->max_height = h; // 最顶上可及
  // this->max_height = h-1; // 最顶上不可及

  this->item_pixel_width = U8G2_CHART_ITEM_PIXEL_WIDTH_DEFAULT; // todo set()

  uint8_t pwg = 0;
  switch (t)
  {
  case LINE:
    pwg = 1; // 1个像素间隔
    break;
  case BAR:
    pwg = 1; // 1个像素间隔
    break;
  default:
    break;
  }
  this->item_pixel_width_gap = pwg;

  this->item_buffer_size = this->width / (this->item_pixel_width + this->item_pixel_width_gap);
  this->item_buffer = new uint8_t[this->item_buffer_size];
}

void U8G2_Graph::SetMinMaxHeight(uint8_t min_height, uint8_t max_height)
{
  this->min_height = min_height;
  this->max_height = max_height;
}

void U8G2_Graph::AddDataPoint(uint16_t val)
{
  uint8_t height = map_val_to_height(val, this->min_val_i, this->max_val_i);
  addDataHeightPoint(height);
}

void U8G2_Graph::AddDataPoint(float val)
{
  uint8_t height = map_val_to_height(val, this->min_val_f, this->max_val_f);
  addDataHeightPoint(height);
}

void U8G2_Graph::addDataHeightPoint(uint8_t height)
{
  if (this->buffer_count < this->item_buffer_size)
  {
    // 缓冲区未满，直接添加到末尾
    this->item_buffer[this->buffer_count] = height;
    this->buffer_count++;
  }
  else
  {
    // 缓冲区已满，所有数据左移一位，丢弃第一个数据
    for (uint8_t i = 0; i < this->item_buffer_size - 1; i++)
    {
      this->item_buffer[i] = this->item_buffer[i + 1];
    }
    this->item_buffer[this->item_buffer_size - 1] = height;
  }
}

uint8_t U8G2_Graph::map_val_to_height(uint16_t val, uint16_t min_val, uint16_t max_val)
{
  // 确保输入值在有效范围内
  if (val < min_val)
    val = min_val;
  if (val > max_val)
    val = max_val;

  // 使用Arduino的map函数进行线性转换
  return map(val, min_val, max_val, this->min_height, this->max_height);
}

uint8_t U8G2_Graph::map_val_to_height(float val, float min_val, float max_val)
{
  // 确保输入值在有效范围内
  if (val < min_val)
    val = min_val;
  if (val > max_val)
    val = max_val;

  // 使用Arduino的map函数进行线性转换
  return map(val, min_val, max_val, this->min_height, this->max_height);
}

void U8G2_Graph::Show()
{
  // u8g2_displayer->drawHLine(0, U8G2_HEIGHT - this->height, this->width);

  // 绘制所有柱状图
  for (uint8_t i = 0; i < this->buffer_count; i++)
  {
    uint8_t draw_height = this->item_buffer[i];
    uint8_t x_pos = i * (this->item_pixel_width + this->item_pixel_width_gap);
    switch (this->type)
    {
    case LINE:
      u8g2_displayer->drawPixel(x_pos + this->x, this->y + this->height - draw_height);
      break;
    case BAR:
      // Serial.printf("draw_height:%d, x_pos:%d, height:%d, width:%d\n", draw_height, x_pos, this->height - draw_height, this->item_pixel_width);
      u8g2_displayer->drawBox(x_pos + this->x, this->y + this->height - draw_height, this->item_pixel_width, draw_height);
      break;
    default:
      break;
    }
  }
}

void U8G2_Graph::Reset()
{
  this->buffer_count = 0;
  memset(this->item_buffer, 0, this->item_buffer_size);
}